package redis.inaction.clients.configuration;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.*;

import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;

//仅仅用来展示Jedis的几种方式
@Configuration
@ConditionalOnProperty(name = "jedis.demonstration", havingValue = "true")
public class JedisUsageConfiguration {

    /**
     * 使用redis作为前缀，配置JedisConfig的属性值,比如
     * redis.maxTotal=5
     * redis.maxIdle=5
     * redis.testOnBorrow=true
     * 还有更多参数: testOnCreate, testOnReturn, testWhileIdle 等等，详细可查阅JedisPoolConfig以及父类的各种属性
     */
    @Bean
    @ConfigurationProperties("redis")
    public JedisPoolConfig jedisPoolConfig() {
        return new JedisPoolConfig();
    }

    /**
     * Jedis 单机(主从)初始化演示
     */
    @ConditionalOnProperty(name = "jedis.demonstration.standalone", havingValue = "true")
    public static class StandaloneDemonstration {
        //使用 redis.host 配置主节点地址
        @Bean(destroyMethod = "close")
        public JedisPool jedisPool(
                @Value("${redis.host:localhost}") String host,
                JedisPoolConfig poolConfig) {
            return new JedisPool(poolConfig, host);
        }
    }

    /**
     * Jedis 集群模式初始化演示
     */
    @ConditionalOnProperty(name = "jedis.demonstration.cluster", havingValue = "true")
    public static class ClusterDemonstration {
        //redis.cluster.nodes=ip:port,ip:port,ip:port
        @Bean
        public JedisCluster jedisCluster(
                @Value("${redis.cluster.nodes}") String clusterNodesStr,
                JedisPoolConfig poolConfig){
            return new JedisCluster(createClusterNodeSet(clusterNodesStr), poolConfig);
        }

        private Set<HostAndPort> createClusterNodeSet(String clusterNodeStr){
            return Arrays.stream(clusterNodeStr.split(","))
                    .map( hostAndPortStr -> {
                        String[] hostAndPort = hostAndPortStr.trim().split(":");
                        return new HostAndPort(hostAndPort[0], new Integer(hostAndPort[1]));
                    }).collect(Collectors.toSet());
        }
    }

    /**
     * Jedis 哨兵模式初始化演示
     */
    @ConditionalOnProperty(name = "jedis.demonstration.sentinel", havingValue = "true")
    public static class SentinelDemonstration{

        //redis.sentinel.nodes=ip:port,ip:port,ip:port
        //redis.sentinel.master_name=xxx
        @Bean
        public JedisSentinelPool jedisSentinelPool(
                @Value("${redis.sentinel.nodes}") String sentinelNodes,
                @Value("${redis.sentinel.master_name}") String masterName,
                JedisPoolConfig poolConfig ){
            Set<String> sentinelNodeSet = Arrays.stream(sentinelNodes.split(","))
                    .collect(Collectors.toSet());
            return new JedisSentinelPool( masterName, sentinelNodeSet, poolConfig);
        }

        /*public void redisOp() {
            try (Jedis jedis = jedisSentinelPool.getResource()) {
                //do redis ops
            }
        }*/
    }
}
